package com.Cfeng.XiaohuanChat.controller;

import com.Cfeng.XiaohuanChat.domain.ChatMessageVo;
import com.Cfeng.XiaohuanChat.entity.ChatMessage;
import com.Cfeng.XiaohuanChat.service.ChatMessageService;
import com.Cfeng.XiaohuanChat.service.ChatUserService;
import com.mysql.cj.util.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.stereotype.Controller;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * @author Cfeng
 * @date 2022/8/3
 * 利用STOMP协议实现消息的控制分发处理
 * 处理的是server的应用程序消息，处理时会去掉/app前缀 -- 配置的
 * 默认情况下，如果不指定Send，会替换/app为/topic
 */

@Controller
@RequiredArgsConstructor
public class ChatController {

    private final SimpMessageSendingOperations messageTemplate;

    private final ChatMessageService messageService;

    private final ChatUserService chatUserService;

    /**
     * @param chatMessageVo  向客户端发送的数据，使用@Paload转换为ChatMessage【messaging.handler中的】
     * 发送到/topic/public 消息broker进行发放推送
     */
    @MessageMapping("/chat.sendMessage")
//    @SendTo("/topic/public")
    public void sendMessage(@Payload ChatMessageVo chatMessageVo) {
        //转发消息时持久化消息类型为Chat的消息
        if(Objects.equals(chatMessageVo.getType(),ChatMessage.MessageType.CHAT)) {
            chatMessageVo.setCreateTime(LocalDateTime.now());
            //存储的是ChatMessage
            ChatMessage message = new ChatMessage()
                    .setSender(chatMessageVo.getSender())
                    .setReceiver(chatMessageVo.getReceiver())
                    .setType(chatMessageVo.getType())
                    .setContent(chatMessageVo.getContent())
                    .setCreateTime(chatMessageVo.getCreateTime());
            //持久化message对象
            messageService.saveChatMessage(message); //需要给出发送消息的时间
        }
//        System.out.println(chatMessageVo.getReceiver());
        //查询user.sender的图像
        chatMessageVo.setSenderHeadImg(chatUserService.queryUser(chatMessageVo.getSender()).getUserHeaderImg());
        //转发时需要注意消息接收者，转发给对应的user 代理发送
        if(StringUtils.isNullOrEmpty(chatMessageVo.getReceiver())) {
            //公共频道,使用模板转换消息为流动的STOMP负载payload，进行流动转发
            messageTemplate.convertAndSend("/topic/public",chatMessageVo);
        } else {
            //私聊服务,只有自己和对方可见消息，所以需要给自己和对方发送消息,路径可以随意，因为识别的是/user/ + 用户标识 + /chat --- 自定义
            messageTemplate.convertAndSendToUser(chatMessageVo.getReceiver(),"/chat",chatMessageVo);
            messageTemplate.convertAndSendToUser(chatMessageVo.getSender(),"/chat",chatMessageVo);
        }
    }

    /**
     * 将消息转发到目的地/topic/public，客户端会订阅/topic/public端点，剩下消息的群发
     * 用户上线消息转发
     * 使用SimpMessageHeaderAccessor消息头访问器访问协议头STOMP
     */
    @MessageMapping("/chat.addUser")
    @SendTo("/topic/public")
    public ChatMessageVo addUser(@Payload ChatMessageVo chatMessageVo, SimpMessageHeaderAccessor headerAccessor) {
        //通过访问器向session中添加username项
        headerAccessor.getSessionAttributes().put("username",chatMessageVo.getSender());
        return chatMessageVo;
    }

    /**
     * 定制消息聊天记录服务供用户订阅
     * 需要查询最新发送的10条记录，分世界频道,这里使用分发
     */
    @SubscribeMapping("/chat.lastTenMessage")
    public List<ChatMessageVo> getMessageHistory(Principal principal) {
        List<ChatMessage> messages = messageService.findWorldLastTenMessage(principal.getName());
        //排序,利用comparator的comparing方法
        messages.sort(Comparator.comparing(ChatMessage::getCreateTime));
        List<ChatMessageVo> resultList = new ArrayList<>();
        for(ChatMessage chatMessage : messages) {
            ChatMessageVo chatMessageVo = new ChatMessageVo();
            chatMessageVo.setSender(chatMessage.getSender())
                    .setContent(chatMessage.getContent())
                    .setReceiver(chatMessage.getReceiver())
                    .setCreateTime(chatMessage.getCreateTime())
                    .setType(chatMessage.getType())
                    .setSenderHeadImg(chatUserService.queryUser(chatMessage.getSender()).getUserHeaderImg());
            resultList.add(chatMessageVo);
        }
        return resultList;
    }
}
